package com.xstudio.pvzreborn.item.armor;

import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ArmorMaterial;
import net.minecraft.world.item.crafting.Ingredient;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class PVZArmorMaterial implements ArmorMaterial {

	private static final Map<String, PVZArmorMaterial> pvzArmorMaterials = new HashMap<>();
	private static final int[] baseDurability = {13, 15, 16, 11};
	private final String name;
	private final int durabilityMultiplier;
	private final int[] armorVal;
	private final int enchantability;
	private final SoundEvent equipSound;
	private final float toughness;
	private final float knockbackResistance;
	private final Supplier<Ingredient> repairIngredient;

	/**
	 * @param name                 盔甲属性名称
	 * @param durabilityMultiplier 耐久度
	 * @param armorVal             四个位置的护甲值
	 * @param enchantability       附魔能力(越大附魔结果越好)
	 * @param equipSound           穿上盔甲的音效
	 * @param toughness            盔甲韧性
	 * @param knockbackResistance  抗击退效果
	 * @param repairIngredient     维修盔甲的材料
	 */

	private PVZArmorMaterial(String name, int durabilityMultiplier, int[] armorVal, int enchantability, SoundEvent equipSound,
	                         float toughness, float knockbackResistance, Supplier<Ingredient> repairIngredient) {
		this.name = name;
		this.durabilityMultiplier = durabilityMultiplier;
		this.armorVal = armorVal;
		this.enchantability = enchantability;
		this.equipSound = equipSound;
		this.toughness = toughness;
		this.knockbackResistance = knockbackResistance;
		this.repairIngredient = repairIngredient;
	}

	public static PVZArmorMaterial registerArmorMaterial(String name, int durabilityMultiplier, int[] armorVal, int enchantability, SoundEvent equipSound,
			float toughness, float knockbackResistance, Supplier<Ingredient> repairIngredient) {
		PVZArmorMaterial armorMaterial = new PVZArmorMaterial(name, durabilityMultiplier, armorVal, enchantability, equipSound, toughness, knockbackResistance, repairIngredient);
		pvzArmorMaterials.put(name, armorMaterial);
		return armorMaterial;
	}

	public static PVZArmorMaterial importArmorMaterial(@Nonnull String name, @Nonnull ArmorMaterial material, @Nullable Integer durabilityMultiplier, @Nullable int[] armorVal, @Nullable Integer enchantability, @Nullable SoundEvent equipSound,
			@Nullable Float toughness, Float knockbackResistance, @Nullable Supplier<Ingredient> repairIngredient) {
		PVZArmorMaterial newMaterial = new PVZArmorMaterial(name,
				durabilityMultiplier == null ? material.getDurabilityForSlot(EquipmentSlot.HEAD) / baseDurability[0] : durabilityMultiplier,
				armorVal == null ? new int[]{material.getDefenseForSlot(EquipmentSlot.HEAD), material.getDefenseForSlot(EquipmentSlot.CHEST), material.getDefenseForSlot(EquipmentSlot.LEGS), material.getDefenseForSlot(EquipmentSlot.FEET)} : armorVal,
				enchantability == null ? material.getEnchantmentValue() : enchantability,
				equipSound == null ? material.getEquipSound() : equipSound,
				toughness == null ? material.getToughness() : toughness,
				knockbackResistance == null ? material.getKnockbackResistance() : knockbackResistance,
				repairIngredient == null ? material::getRepairIngredient : repairIngredient
		);
		pvzArmorMaterials.put(name, newMaterial);
		return newMaterial;
	}

	public static PVZArmorMaterial importArmorMaterial(@Nonnull String name, @Nonnull ArmorMaterial material) {
		return registerArmorMaterial(name, material.getDurabilityForSlot(EquipmentSlot.HEAD) / baseDurability[0], new int[]{material.getDefenseForSlot(EquipmentSlot.HEAD), material.getDefenseForSlot(EquipmentSlot.CHEST), material.getDefenseForSlot(EquipmentSlot.LEGS), material.getDefenseForSlot(EquipmentSlot.FEET)}, material.getEnchantmentValue(), material.getEquipSound(), material.getToughness(), material.getKnockbackResistance(), material::getRepairIngredient);
	}

	public static PVZArmorMaterial getArmorMaterial(String name) {
		return Objects.requireNonNull(pvzArmorMaterials.get(name), "无法获取盔甲属性:" + name);
	}

	@Override
	public int getDurabilityForSlot(EquipmentSlot slot) {
		return baseDurability[slot.getIndex()] * durabilityMultiplier;
	}

	@Override
	public int getDefenseForSlot(EquipmentSlot slot) {
		return this.armorVal[slot.getIndex()];
	}

	@Override
	public int getEnchantmentValue() {
		return this.enchantability;
	}

	@NotNull
	@Override
	public SoundEvent getEquipSound() {
		return this.equipSound;
	}

	@NotNull
	public Ingredient getRepairIngredient() {
		return this.repairIngredient.get();
	}

	@NotNull
	@Override
	public String getName() {
		return "pvzreborn:" + this.name;
	}

	@Override
	public float getToughness() {
		return this.toughness;
	}

	@Override
	public float getKnockbackResistance() {
		return this.knockbackResistance;
	}

}
